/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/


const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class myPromise {
    // 构造器
    constructor(executor) {

        let _this = this;
        this.state = PENDING; //状态
        this.value = undefined; //成功结果
        this.reason = undefined; //失败结果

        // 成功存放的数组
        this.onResolvedCallbacks = [];
        // 失败存放法数组
        this.onRejectedCallbacks = [];
        // 成功
        let resolve = (value) => {
            if (this.state === 'pending') {
                // resolve调用后，state转化为成功态
                this.state = FULFILLED;
                // 储存成功的值
                this.value = value;

                _this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        // 失败
        let reject = (reason) => {
            // state改变,reject调用就会失败
            if (this.state === 'pending') {
                // reject调用后，state转化为失败态
                this.state = REJECTED;
                // 储存失败的原因
                this.reason = reason;
                // 一旦reject执行，调用失败数组的函数
                _this.onRejectedCallbacks.forEach(fn => fn());
            }
        };
        // 如果executor执行报错，直接执行reject
        try {
            executor(resolve, reject);
        } catch (err) {
            reject(err);
        }
    }
    then(onFulfilled, onRejected) {
        // onFulfilled如果不是函数，就忽略onFulfilled，直接返回value
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        // onRejected如果不是函数，就忽略onRejected，直接扔出错误
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };

        let promise2 = new Promise((resolve, reject) => {
            if (this.state === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value);
                        this.resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);

            }
            if (this.state === REJECTED) {
                setTimeout(() => {
                    // 如果报错
                    try {
                        let x = onRejected(this.reason);
                        this.resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }

            if (this.state === PENDING) {
                this.onResolvedCallbacks.push(() => {
                    // 异步
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            this.resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
                this.onRejectedCallbacks.push(() => {
                    // 异步
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            this.resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)
                });
            }
        });

        return promise2;
    }
    catch (fn) {
        return this.then(null, fn);
    }
    resolvePromise(promise2, x, resolve, reject) {
        // 循环引用报错
        if (x === promise2) {
            // reject报错
            return reject(new TypeError('Chaining cycle detected for promise'));
        }
        // 防止多次调用
        let called;
        // x不是null 且x是对象或者函数
        if (x != null && (typeof x === 'object' || typeof x === 'function')) {
            try {
                //声明then = x的then方法
                let then = x.then;
                // 如果then是函数，就默认是promise了
                if (typeof then === 'function') {
                    // 就让then执行 第一个参数是this   后面是成功的回调 和 失败的回调
                    then.call(x, y => {
                        // 成功和失败只能调用一个
                        if (called) return;
                        called = true;
                        // resolve的结果依旧是promise 那就继续解析
                        resolvePromise(promise2, y, resolve, reject);
                    }, err => {
                        // 成功和失败只能调用一个
                        if (called) return;
                        called = true;
                        reject(err); // 失败了就失败了
                    })
                } else {
                    resolve(x); // 直接成功即可
                }
            } catch (e) {
                // 也属于失败
                if (called) return;
                called = true;
                // 取then出错了那就不要在继续执行了
                reject(e);
            }
        } else {
            resolve(x);
        }
    }

}